package cn.org.xwb.bookmall.admin.controller;

import cn.hutool.core.convert.Convert;
import cn.org.xwb.bookmall.admin.annotation.IsLoginParam;
import cn.org.xwb.bookmall.model.constant.AccountConst;
import cn.org.xwb.bookmall.model.mapper.ManagerMapper;
import cn.org.xwb.bookmall.model.po.Manager;
import cn.org.xwb.bookmall.model.po.User;
import cn.org.xwb.bookmall.model.po.UserAllInfo;
import cn.org.xwb.bookmall.model.properties.AccountProp;
import cn.org.xwb.bookmall.model.utils.BookCodeUtil;
import cn.org.xwb.bookmall.model.utils.BookRedisUtil;
import cn.org.xwb.bookmall.model.vo.ManagerVo;
import cn.org.xwb.bookmall.model.vo.UserAllInfoVo;
import cn.org.xwb.bookmall.model.vo.UserVo;
import cn.org.xwb.common.encrypt.annotation.des.DesEn;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDe;
import cn.org.xwb.common.encrypt.annotation.rsa.RsaDeParam;
import cn.org.xwb.common.encrypt.constant.EncryptConstant;
import cn.org.xwb.common.encrypt.utils.SHAUtil;
import cn.org.xwb.common.model.vo.RespResult;
import cn.org.xwb.common.redis.utils.RedisUtil;
import cn.org.xwb.common.valid.annotation.nu.NotNull;
import cn.org.xwb.common.valid.annotation.nu.NotNullParam;
import cn.org.xwb.common.valid.annotation.str.StrNotNull;
import cn.org.xwb.common.valid.annotation.str.StrNotNullParam;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Objects;

@RestController
@RequestMapping("/admin")
public class XwbAdminController {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private BookRedisUtil bookRedisUtil;

    @GetMapping("/all")
    @StrNotNull
    @RsaDe
    @IsLoginParam
    @DesEn
    public RespResult<Object> getUserAllInfo(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String desKey
    ) {
        // 从缓存中获取
        Manager manager = (Manager) redisUtil.get(bookRedisUtil.getRedisKeyAdmin(AccountConst.ACCOUNT, account));
        ManagerVo managerVo = Convert.convert(ManagerVo.class, manager);
        return RespResult.success("获取管理员信息成功", managerVo);
    }

    @Autowired
    private ManagerMapper managerMapper;

    @Autowired
    private AccountProp accountProp;

    private Manager findAndCache(Long id) {
        Manager manager = managerMapper.selectById(id);
        // 缓存
        boolean res = redisUtil.setVal(
                bookRedisUtil.getRedisKeyAdmin(AccountConst.ACCOUNT, manager.getAccount()),
                manager,
                accountProp.getAccountCacheExpireAdmin(),
                accountProp.getAccountCacheExpireAdminUnit()
        );
        if (!res) return null;
        return manager;
    }

    @PostMapping("/avatar")
    @NotNull
    @StrNotNull
    @RsaDe
    @IsLoginParam
    @DesEn
    public RespResult<Object> updateAvatar(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String desKey,
            @RequestParam("avatar")
            @StrNotNullParam @RsaDeParam
            String avatar,
            @RequestParam("id")
            @NotNullParam
            Long id
    ) {
        Manager manager = new Manager();
        manager.setId(id);
        manager.setAvatar(avatar);
        int res = managerMapper.updateById(manager);
        if (res < 1) return RespResult.fail("更换头像失败，请重新尝试");
        // 刷新缓存
        manager = findAndCache(id);
        if (Objects.isNull(manager)) return RespResult.fail("更换头像失败，请重新尝试");
        return RespResult.success("更换头像成功", Convert.convert(ManagerVo.class, manager));
    }

    @PostMapping("/username")
    @NotNull
    @StrNotNull
    @RsaDe
    @IsLoginParam
    @DesEn
    public RespResult<Object> updateUsername(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam(EncryptConstant.DES_KEY_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String desKey,
            @RequestParam("username")
            @StrNotNullParam @RsaDeParam
            String username,
            @RequestParam("id")
            @NotNullParam
            Long id
    ) {
        // 查询用户名是否存在
        LambdaQueryWrapper<Manager> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Manager::getUsername, username);
        Manager manager = managerMapper.selectOne(queryWrapper);
        if (Objects.nonNull(manager) && manager.getId() != id) return RespResult.fail("用户名已存在");
        // 更新用户名
        manager = new Manager();
        manager.setId(id);
        manager.setUsername(username);
        int res = managerMapper.updateById(manager);
        if (res < 1) return RespResult.fail("更换用户名失败，请重新尝试");
        // 刷新缓存
        manager = findAndCache(id);
        if (Objects.isNull(manager)) return RespResult.fail("更换用户名失败，请重新尝试");
        return RespResult.success("更换用户名成功", Convert.convert(ManagerVo.class, manager));
    }

    @PostMapping("/pwd")
    @NotNull
    @StrNotNull
    @RsaDe
    @IsLoginParam
    public RespResult<Object> updatePwd(
            @RequestParam(AccountConst.ACCOUNT_PARAM_NAME)
            @StrNotNullParam @RsaDeParam
            String account,
            @RequestParam("pwd")
            @StrNotNullParam @RsaDeParam
            String pwd,
            @RequestParam("id")
            @NotNullParam
            Long id
    ) {
        // 从缓存获取用户信息
        Manager manager = (Manager) redisUtil.get(bookRedisUtil.getRedisKeyAdmin(AccountConst.ACCOUNT, account));
        // 修改密码
        manager.setPwd(SHAUtil.encryptBySHA256(manager.getSalt(), pwd));
        int res = managerMapper.updateById(manager);
        if (res < 1) return RespResult.fail("修改密码失败，请重新尝试");
        // 刷新缓存
        manager = findAndCache(id);
        if (Objects.isNull(manager)) return RespResult.fail("修改密码失败，请重新尝试");
        return RespResult.success("修改密码成功", Convert.convert(ManagerVo.class, manager));
    }

}
